import logging
import shutil
from pathlib import Path

from fastapi import APIRouter

from app.models import EBRResponse, TQCDataRequest
from app.utils.buildAb import run_buildAb
from app.utils.common_utils import (
    ProcessingError,
    change_directory,
    determine_soc,
    setup_cache_directory,
    setup_tqc_data,
)

router = APIRouter()
logger = logging.getLogger(__name__)


async def process_ebr_decomp(cache_dir: Path):
    """处理EBR分解"""
    try:
        # 使用绝对路径
        soc = determine_soc(cache_dir / "tqc.data")
        logger.info(f"确定SOC状态码: {soc}")

        atomwp_temp_path = cache_dir / ("atomwp.in")
        source_file = cache_dir / ("fort.701" if soc else "fort.601")
        result_file = cache_dir / "decompose_tqc.data"

        if not source_file.exists():
            raise ProcessingError(f"源文件 {source_file} 不存在，无法进行EBR分解，请先执行POS2ABR")
        if result_file.exists():
            result_file.unlink()

        shutil.copy(source_file, atomwp_temp_path)

        # 运行buildAb，需要在cache_dir中执行
        with change_directory(cache_dir):
            run_buildAb("tqc.data", soc)

        posout_path = cache_dir / "posout"
        decompose_ebr_path = cache_dir / "decompose.601"

        posout_content = posout_path.read_text()

        if not result_file.exists():
            raise ProcessingError("EBR分解未能生成 decompose_tqc.data 文件")
        shutil.copy(result_file, decompose_ebr_path)
        logger.info(f"已生成EBR分解文件: {decompose_ebr_path}")

        decompose_ebr_content = decompose_ebr_path.read_text()
        lines = decompose_ebr_content.splitlines()

        try:
            num_solutions = int(lines[0].strip()) if lines else 0
        except (ValueError, IndexError):
            logger.warning(f"无法从 {decompose_ebr_path} 解析解的数量")
            num_solutions = -1

        result = {
            "status": "success",
            "soc": soc,
            "abrs": posout_content,
            "num_solutions": num_solutions,
            "decompose_ebr_content": decompose_ebr_content,
        }

        if num_solutions == 0:
            result["is_topological"] = True
            result["conclusion"] = (
                "It's topological, since there is no solution for eBR decomposition. Please further check the compatibility relations (CRs)."
            )
            result["additional_data"] = {
                "details": "If satisfying CRs, it is a topological insulator; otherwise, it is a topological semimetal."
            }
        elif num_solutions == -1:
            result["is_topological"] = "Undetermined"
            result["conclusion"] = "Error in eBR decomposition, please check the input files."
        else:
            result["is_topological"] = False
            result["conclusion"] = "Not topological, since there are solutions for eBR decomposition."

        return EBRResponse.model_validate(result)
    except ProcessingError:
        raise
    except Exception as e:
        raise ProcessingError(f"EBR分解处理中发生意外错误: {str(e)}") from e


@router.post(
    "/ebr_decomp",
    summary="电子带表示(eBR)分解",
    description="执行电子带表示分解，分析材料的拓扑性质，判断是否为拓扑材料",
    response_description="返回eBR分解结果和拓扑性质判断",
    response_model=EBRResponse,
)
async def ebr_decomposition(request: TQCDataRequest):
    """
    ## 电子带表示(eBR)分解分析

    执行电子带表示分解，基于群论和拓扑理论分析材料的电子结构和拓扑性质。

    ### 功能说明：
    - 分析材料的电子带结构
    - 进行eBR分解计算
    - 判断材料的拓扑性质
    - 确定是否为拓扑材料

    ### 输入参数：
    - **poscar_content**: POSCAR文件的完整内容
    - **tqc_data**: TQC(Topological Quantum Chemistry)数据文件内容，包含占据带信息

    ### 返回结果：
    - **status**: 处理状态 ("success" 或 "error")
    - **soc**: 是否包含自旋轨道耦合效应
    - **abrs**: 原子带表示列表，包含原子轨道信息
    - **num_solutions**: eBR分解的解的数量
    - **decompose_content**: 详细的分解结果内容
    - **is_topological**: 是否为拓扑材料的判断结果
    - **conclusion**: 分析结论和总结
    - **additional_data**: 其他相关数据和信息
    ```
    """
    cache_dir = setup_cache_directory(request.poscar_content)
    setup_tqc_data(cache_dir, request.tqc_data)
    return await process_ebr_decomp(cache_dir)
